package com.st.event.demo.scanner;

import com.st.event.demo.annotation.EventProvider;
import com.st.event.demo.proxy.bean.EventProviderFactoryBean;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Set;

public abstract class EventListenerAbstractRegistryScanner extends ClassPathBeanDefinitionScanner {

    public boolean acceptAllInterfaces = false;

    protected EventProviderFactoryBean<?> factoryBean = new EventProviderFactoryBean<>();

    protected Class<? extends Annotation>[] annotations = new Class[]{EventProvider.class};

    public EventListenerAbstractRegistryScanner(BeanDefinitionRegistry registry) {
        super(registry, false);
    }

    @Override
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        System.out.println("执行4-----------");
        Set<BeanDefinitionHolder> holders = super.doScan(basePackages);
        if (holders.isEmpty()) {
            System.out.println("No interface was found in '" + Arrays.toString(basePackages) + "' package.");
        } else {
            processBeanDefinitions(holders);
        }
        return holders;
    }

    protected abstract void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions);

    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
    }

    public void registerFilters() {
        System.out.println("执行5-----------");
        if (acceptAllInterfaces) {
            addIncludeFilter((metadataReader, metadataReaderFactory) -> true);
        } else {
            for (Class<? extends Annotation> annotation : annotations) {
                addIncludeFilter(new AnnotationTypeFilter(annotation));
            }
        }

        addExcludeFilter((metadataReader, metadataReaderFactory) -> {
            String className = metadataReader.getClassMetadata().getClassName();
            return className.endsWith("package-info");
        });
    }


    public EventProviderFactoryBean<?> getFactoryBean() {
        return factoryBean;
    }

    public void setAcceptAllInterfaces(boolean acceptAllInterfaces) {
        this.acceptAllInterfaces = acceptAllInterfaces;
    }
}
